﻿using HslCommunication;
using HslCommunication.Profinet.Melsec;
using HslCommunication.Profinet.Omron.Helper;
using PLCDataCollector.Core.Entities;
using PLCDataCollector.Core.Interfaces;
using PLCDataCollector.Core.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PLCDataCollector.Services.PLC
{
    public class MelsecA1EAsciiNetService : IPLCService
    {
        private readonly MelsecA1EAsciiNet _melsecMc;
        public string ProtocolType => "MelsecA1EAsciiNet";

        public MelsecA1EAsciiNetService(string ip, int port)
        {
            _melsecMc = new MelsecA1EAsciiNet(ip, port);
            _melsecMc.ConnectTimeOut = 3000;
        }

        public bool Connect()
        {
            try
            {
                var result = _melsecMc.ConnectServer();
                IsConnected = result.IsSuccess;
                return result.IsSuccess;
            }
            catch (Exception ex)
            {
                // 记录日志
                return false;
            }
        }

        public void Disconnect()
        {
            _melsecMc.ConnectClose();
            IsConnected = false;
        }
        public OperateResult<object> ReadData(DeviceMappingDetail detail)
        {
            switch (detail.DataType.ToLower())
            {
                case "bool":
                    var boolResult = _melsecMc.ReadBool(detail.DataAddress);
                    return ConvertOperateResult(boolResult);
                case "int16":
                    var shortResult = _melsecMc.ReadInt16(detail.DataAddress);
                    return ConvertOperateResult(shortResult);
                case "int32":
                    var intResult = _melsecMc.ReadInt32(detail.DataAddress);
                    return ConvertOperateResult(intResult);
                case "float":
                    var floatResult = _melsecMc.ReadFloat(detail.DataAddress);
                    return ConvertOperateResult(floatResult);
                case "string":
                    var stringResult = _melsecMc.ReadString(detail.DataAddress, 5);
                    return ConvertOperateResult(stringResult);
                default:
                    return new OperateResult<object>($"不支持的数据类型: {detail.DataType}");
            }
        }

        public OperateResult WriteData(PlcWriteModel detail)
        {
            switch (detail.DataType.ToLower())
            {
                case "bool":
                    var boolResult = _melsecMc.Write(detail.DataAddress, Convert.ToBoolean(detail.DataValue));
                    return boolResult;
                case "int16":
                    var shortResult = _melsecMc.Write(detail.DataAddress, Convert.ToInt16(detail.DataValue));
                    return shortResult;
                case "int32":
                    var intResult = _melsecMc.Write(detail.DataAddress, Convert.ToInt32(detail.DataValue));
                    return intResult;
                case "string":
                    var stringResult = _melsecMc.Write(detail.DataAddress, detail.DataValue.ToString());
                    return stringResult;
                default:
                    return new OperateResult<object>($"不支持的数据类型: {detail.DataType}");
            }
        }

        private OperateResult<object> ConvertOperateResult<T>(OperateResult<T> result)
        {
            if (result.IsSuccess)
            {
                return new OperateResult<object>
                {
                    Content = result.Content, // 将具体类型的数据装箱为object
                    IsSuccess = result.IsSuccess,
                    Message = result.Message,
                    ErrorCode = result.ErrorCode
                };
            }
            else
            {
                return new OperateResult<object>
                {
                    IsSuccess = result.IsSuccess,
                    Message = result.Message,
                    ErrorCode = result.ErrorCode
                };
            }
        }


        public bool IsBreak { get; set; }

        public bool IsConnected { get; private set; }
    }
}
